#include "rtspserver1.h"

RtspServer1::RtspServer1(QObject *parent)
    : QObject{parent}
{
    m_server = NULL;
    m_socket = NULL;
    m_bConnected = false;
}

RtspServer1::~RtspServer1()
{
    OnClosed();
    delete m_socket;
    delete m_server;
    m_server = NULL;
    m_socket = NULL;
}

void RtspServer1::start()
{
    m_server = new QTcpServer(this);
    if(m_server) {
        bool ret = m_server->listen(QHostAddress::Any, SERVER_PORT);
        if(ret) {
            qDebug() << QString("服务器监听端口:%1").arg(SERVER_PORT);
            connect(m_server, &QTcpServer::newConnection, this, &RtspServer1::OnNewConnection);
        }
    }
}

void RtspServer1::OnNewConnection()
{
    m_socket = m_server->nextPendingConnection();
    if(m_socket) {
        connect(m_socket, &QTcpSocket::readyRead, this, &RtspServer1::OnRecv);
        quint32 ip4 = m_socket->peerAddress().toIPv4Address();
        QHostAddress addrOrign = QHostAddress(ip4);

        clientIP = addrOrign.toString();
        clientPort = m_socket->peerPort();
    }
}

void RtspServer1::OnRecv()
{
    QString msg = m_socket->readAll();
    qDebug() << QString("msg:%1").arg(msg);
    OnMessage(msg);
}

void RtspServer1::OnMessage(QString recvMsg)
{
    QStringList msgList = recvMsg.split("\n");

    char method[40];
    char url[100];
    char version[40];
    int CSeq;

    int clientRtpPort, clientRtcpPort;
    for(int i = 0; i < msgList.size(); i++) {
        QString msg = msgList.at(i);
        if(msg.contains(OPTIONS) || msg.contains(DESCRIBE)
            || msg.contains(SETUP) || msg.contains(PLAY)) {
            if(sscanf(msg.toStdString().c_str(), "%s %s %s\r\n", method, url, version) != 3) {
                //error
            }
        } else if(msg.contains(CSEQ)) {
            if (sscanf(msg.toStdString().c_str(), "CSeq: %d\r\n", &CSeq) != 1) {
                //error
            }
        } else if(msg.contains(SETUP)) {
            if (sscanf(msg.toStdString().c_str(), "Transport: RTP/AVP/UDP;unicast;client_port=%d-%d\r\n",
                       &clientRtpPort, &clientRtcpPort) != 2) {
                // error
            }
        }
    }

    char* rBuf = (char*)malloc(10000);
    char* sBuf = (char*)malloc(10000);
    if (!strcmp(method, OPTIONS)) {
        if (handleCmd_OPTIONS(sBuf, CSeq)) {
            qDebug() << QString("failed to handle options");
        }
    } else if (!strcmp(method, DESCRIBE)) {
        if (handleCmd_DESCRIBE(sBuf, CSeq, url)) {
            qDebug() << QString("failed to handle describe");
        }
    } else if (!strcmp(method, SETUP)) {
        if (handleCmd_SETUP(sBuf, CSeq, clientRtpPort)) {
            qDebug() << QString("failed to handle setup\n");
        }
    } else if (!strcmp(method, "PLAY")) {
        if (handleCmd_PLAY(sBuf, CSeq)) {
            qDebug() << QString("failed to handle play\n");
        }
    } else {
        printf("未定义的method = %s \n", method);
    }

    qDebug() << QString("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
    qDebug() << QString("sBuf = %1").arg(sBuf);
    m_socket->write(sBuf, strlen(sBuf));

}

void RtspServer1::OnClosed()
{
    if(m_socket)
        m_socket->close();
    if(m_server)
        m_server->close();
}

int RtspServer1::handleCmd_OPTIONS(char* result, int cseq)
{
    sprintf(result, "RTSP/1.0 200 OK\r\n"
                    "CSeq: %d\r\n"
                    "Public: OPTIONS, DESCRIBE, SETUP, PLAY\r\n"
                    "\r\n",
            cseq);

    return 0;
}

int RtspServer1::handleCmd_DESCRIBE(char *result, int cseq, char *url)
{
    char sdp[500];
    char localIp[100];

    sscanf(url, "rtsp://%[^:]:", localIp);

    sprintf(sdp, "v=0\r\n"
                 "o=- 9%ld 1 IN IP4 %s\r\n"
                 "t=0 0\r\n"
                 "a=control:*\r\n"
                 "m=video 0 RTP/AVP 96\r\n"
                 "a=rtpmap:96 H264/90000\r\n"
                 "a=control:track0\r\n",
            time(NULL), localIp);

    sprintf(result, "RTSP/1.0 200 OK\r\nCSeq: %d\r\n"
                    "Content-Base: %s\r\n"
                    "Content-type: application/sdp\r\n"
                    "Content-length: %zu\r\n\r\n"
                    "%s",
            cseq,
            url,
            strlen(sdp),
            sdp);

    return 0;
}

int RtspServer1::handleCmd_SETUP(char *result, int cseq, int clientRtpPort)
{
    sprintf(result, "RTSP/1.0 200 OK\r\n"
                    "CSeq: %d\r\n"
                    "Transport: RTP/AVP;unicast;client_port=%d-%d;server_port=%d-%d\r\n"
                    "Session: 66334873\r\n"
                    "\r\n",
            cseq,
            clientRtpPort,
            clientRtpPort + 1,
            SERVER_RTP_PORT,
            SERVER_RTCP_PORT);

    return 0;
}

int RtspServer1::handleCmd_PLAY(char *result, int cseq)
{
    sprintf(result, "RTSP/1.0 200 OK\r\n"
                    "CSeq: %d\r\n"
                    "Range: npt=0.000-\r\n"
                    "Session: 66334873; timeout=10\r\n\r\n",
            cseq);

    return 0;
}
